package com.d3works.apps.account.service;

import com.d3works.apps.account.db.InvoicePayment;
import com.d3works.apps.account.db.InvoiceTerm;
import com.d3works.apps.account.db.InvoiceTermPayment;
import com.d3works.apps.account.db.MoveLine;
import com.d3works.apps.account.db.Reconcile;
import com.d3works.apps.base.db.Partner;
import com.d3works.exception.D3worksException;
import com.google.inject.persist.Transactional;
import java.math.BigDecimal;
import java.util.List;

public interface ReconcileService {

  @Transactional
  public Reconcile createReconcile(
      MoveLine debitMoveLine,
      MoveLine creditMoveLine,
      BigDecimal amount,
      boolean canBeZeroBalanceOk);

  @Transactional(rollbackOn = {Exception.class})
  public Reconcile confirmReconcile(
      Reconcile reconcile, boolean updateInvoicePayments, boolean updateInvoiceTerms)
      throws D3worksException;

  public void reconcilePreconditions(Reconcile reconcile) throws D3worksException;

  public void updatePartnerAccountingSituation(Reconcile reconcile) throws D3worksException;

  public List<Partner> getPartners(Reconcile reconcile);

  Reconcile reconcile(
      MoveLine debitMoveLine,
      MoveLine creditMoveLine,
      boolean canBeZeroBalanceOk,
      boolean updateInvoicePayments,
      InvoicePayment invoicePayment)
      throws D3worksException;

  public Reconcile reconcile(
      MoveLine debitMoveLine,
      MoveLine creditMoveLine,
      boolean canBeZeroBalanceOk,
      boolean updateInvoicePayments)
      throws D3worksException;

  Reconcile reconcile(
      MoveLine debitMoveLine,
      MoveLine creditMoveLine,
      InvoicePayment invoicePayment,
      boolean canBeZeroBalanceOk,
      boolean updateInvoicePayments)
      throws D3worksException;

  @Transactional(rollbackOn = {Exception.class})
  public void unreconcile(Reconcile reconcile) throws D3worksException;

  @Transactional(rollbackOn = {Exception.class})
  public void canBeZeroBalance(Reconcile reconcile) throws D3worksException;

  public void balanceCredit(MoveLine creditMoveLine) throws D3worksException;

  public List<Reconcile> getReconciles(MoveLine moveLine);

  /**
   * Add a reconcile to an existing or created reconcile group.
   *
   * @param reconcile a confirmed reconcile.
   */
  void addToReconcileGroup(Reconcile reconcile) throws D3worksException;

  public static boolean isReconcilable(MoveLine acc1, MoveLine acc2) {
    return acc1.getAccount().getReconcileOk()
        && acc2.getAccount().getReconcileOk()
        && (acc1.getAccount().equals(acc2.getAccount())
            || acc1.getAccount().getCompatibleAccountSet().contains(acc2.getAccount()));
  }

  public List<InvoiceTermPayment> updateInvoiceTerms(
      List<InvoiceTerm> invoiceTermList,
      InvoicePayment invoicePayment,
      BigDecimal amount,
      Reconcile reconcile)
      throws D3worksException;

  void checkReconcile(Reconcile reconcile) throws D3worksException;

  List<Long> getAllowedMoveLines(Reconcile reconcile, boolean isDebit);
}
